package com.iflytek.read.util;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author wangshuai
 */
public class ThreadPoolUtils {

    /**
     * 创建固定大小的线程池
     * @param poolSize 线程池大小
     * @param threadNamePrefix 线程名前缀
     * @return 线程池
     */
    public static ExecutorService newFixedThreadPool(int poolSize, String threadNamePrefix) {
        return new ThreadPoolExecutor(
                poolSize,
                poolSize,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(),
                new NamedThreadFactory(threadNamePrefix),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 创建单线程的线程池
     * @param threadNamePrefix 线程名前缀
     * @return 线程池
     */
    public static ExecutorService newSingleThreadExecutor(String threadNamePrefix) {
        return new ThreadPoolExecutor(
                1,
                1,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(),
                new NamedThreadFactory(threadNamePrefix),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 创建可缓存的线程池
     * @param threadNamePrefix 线程名前缀
     * @return 线程池
     */
    public static ExecutorService newCachedThreadPool(String threadNamePrefix) {
        return new ThreadPoolExecutor(
                0,
                Integer.MAX_VALUE,
                60L,
                TimeUnit.SECONDS,
                new SynchronousQueue<>(),
                new NamedThreadFactory(threadNamePrefix),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 自定义线程工厂，用于设置线程名称
     */
    private static class NamedThreadFactory implements ThreadFactory {
        private final String namePrefix;
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        NamedThreadFactory(String namePrefix) {
            this.namePrefix = namePrefix + "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }
}